package subraSoft.centaurus.gui;

import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyVetoException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Set;

import javax.swing.ImageIcon;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.KeyStroke;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import subraSoft.centaurus.gui.components.CenAbout;
import subraSoft.centaurus.gui.components.CenSplashScreen;
import subraSoft.centaurus.gui.util.CenImageUtil;
import subraSoft.centaurus.gui.window.CenInternalFrame;
import subraSoft.centaurus.gui.window.CenOptionMenuItem;
import subraSoft.centaurus.model.util.CenConfigurationUtil;

/**
 * Clase generica con la estructura y menues basicos de la aplicacion.
 * 
 * @author christian
 *
 */
public abstract class CenApplication implements ActionListener
{
	//COMPONENTES
	/**
	 * Frame sobre la que esta montada toda la aplicacion.
	 */
	public static JFrame frame							= null;
	private static String user;

	protected JDesktopPane desktop						= null;

	// MENU
	protected JMenuBar menuBar;
	protected JMenu appMnu, helpMnu;
	protected JMenuItem cerrarMni, aboutMni;



	/**
	 * Crea la interfaz grafica.
	 */
	protected void createSplash(int splashTime)
	{
		ImageIcon res = CenImageUtil.getInstance().getIcon("splash.png");
		CenSplashScreen splash = new CenSplashScreen(res, splashTime);
		splash.run();
	}

	/**
	 * Crea la interfaz grafica.
	 */
	public void create()
	{
		frame = new JFrame(getAppTitle());

		frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

		frame.addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				cerrarSesionFenix();
			}
		}
		);

		frame.setIconImage( CenImageUtil.getInstance().getImage("icon.png") );

		// Para que al setear la aplicacion en espera no se puedan realizar acciones
		frame.getGlassPane().addMouseListener( new java.awt.event.MouseAdapter() { } ); 

		desktop = new JDesktopPane();
		desktop.setBackground(Color.gray);
		frame.setContentPane(desktop);
		desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);

		createMenu();

		int inset = 50;
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		frame.setBounds(inset, inset, screenSize.width  - inset*2, screenSize.height - inset*2);
		frame.setVisible(true);
	}

	/**
	 * Crea el menu.
	 */
	private void createMenu()
	{
		menuBar = new JMenuBar();
		appMnu = new JMenu(getAppTitle());
		appMnu.setEnabled(true);
		appMnu.setMnemonic(KeyEvent.VK_Z);
		appMnu.getAccessibleContext().setAccessibleDescription("");
		menuBar.add(appMnu);

		cerrarMni = new JMenuItem("Cerrar...",KeyEvent.VK_E);
		cerrarMni.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E, ActionEvent.CTRL_MASK));
		cerrarMni.getAccessibleContext().setAccessibleDescription("");
		cerrarMni.addActionListener( this );
		cerrarMni.setIcon(CenImageUtil.getInstance().getIcon("img/exit.png"));
		appMnu.add(cerrarMni);

		try{
			createAppMenu("menu.xml");
		}catch(Exception e)
		{
			e.printStackTrace();
		} // TODO

		//menuBar.add(Box.createHorizontalGlue());

		helpMnu = new JMenu("Ayuda");
		helpMnu.setEnabled(true);
		helpMnu.getAccessibleContext().setAccessibleDescription("");
		menuBar.add(helpMnu);

		aboutMni = new JMenuItem("Acerca de...", KeyEvent.VK_H);
		aboutMni.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H, ActionEvent.CTRL_MASK));
		aboutMni.getAccessibleContext().setAccessibleDescription("");
		aboutMni.addActionListener( this );
		aboutMni.setIcon(CenImageUtil.getInstance().getIcon("img/help.png"));
		helpMnu.add(aboutMni);


		frame.setJMenuBar(menuBar);	
	}

	// ---------------------------------------------------------------//	
	// ACTIONS
	// ---------------------------------------------------------------//

	@SuppressWarnings("unchecked")
	public void actionPerformed(ActionEvent e) 
	{
		if ( e.getSource() == cerrarMni )
		{
			cerrarSesionFenix();
		}
		else if ( e.getSource() == aboutMni )
		{
			new CenAbout();
		}
		else if( e.getSource() instanceof CenOptionMenuItem)
		{
			CenOptionMenuItem op = (CenOptionMenuItem)e.getSource();
			
			CenInternalFrame internaFrame = null;
			try {
				Class optionClass = Class.forName( op.getClassName() );
				internaFrame = (CenInternalFrame) optionClass.newInstance();
			} catch (Exception e2) {
				//TODO
				e2.printStackTrace();
				System.exit(-1);
			}
			
			setBusyCursor(true);
			internaFrame.create();
			desktop.add(internaFrame);
			setBusyCursor(false);
			
			try 
			{
				internaFrame.setSelected(true);
			} 
			catch (PropertyVetoException e1) 
			{
				// SI NO PUEDO SELECCIONARLA NO HAY PROBLEMA
			}
		}
	}

	private void cerrarSesionFenix()
	{
		System.exit(0);
	}

	// ---------------------------------------------------------------//	
	// DE LA APP
	// ---------------------------------------------------------------//


	protected abstract String getAppTitle();

	public static void setBusyCursor(boolean busy)
	{
		Component c = frame.getGlassPane();

		if(busy)
		{
			//c.addMouseListener( new java.awt.event.MouseAdapter() { } );
			c.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
			c.setVisible(true);
		}
		else
		{
			c.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
			c.setVisible(false);
		}
	}

	protected void createAppMenu(String file) throws ParserConfigurationException, SAXException, IOException
	{
		InputStream is = CenConfigurationUtil.class.getClassLoader().getResourceAsStream(file);
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = dbf.newDocumentBuilder();
		Document doc = db.parse(is);
		doc.getDocumentElement().normalize();

		NodeList menuList = doc.getFirstChild().getChildNodes();

		for (int i = 0; i < menuList.getLength(); i++)
		{
			Node e = (Node) menuList.item(i);
			if(e.getNodeType() == Node.ELEMENT_NODE)
				menuBar.add(createMenu((Element) e));
		}

	}

	private JMenuItem createMenu(Element element)
	{
		if(element.getTagName().equals("menu"))
		{
			JMenu menu = new JMenu();
			menu.setText(element.getAttribute("label"));

			NodeList menuList = element.getChildNodes();
			for (int i = 0; i < menuList.getLength(); i++)
			{
				Node e = menuList.item(i);
				if(e.getNodeType() == Node.ELEMENT_NODE)
					menu.add(createMenu((Element) e));
			}
			return menu;
		}
		else
		{
			CenOptionMenuItem item = new CenOptionMenuItem();
			item.setText(element.getAttribute("label"));
			item.setClassName(element.getAttribute("class"));
			item.setId(element.getAttribute("id"));
			item.setShortcut(element.getAttribute("key").charAt(0)); //TODO
			item.setAuthenticable(Boolean.parseBoolean( element.getAttribute("authenticable") ));
			item.setIcon( CenImageUtil.getInstance().getIcon( element.getAttribute("icon") ));
			System.out.println("---------- " + item.getShortcut());
			item.setAccelerator(KeyStroke.getKeyStroke( item.getShortcut(), Event.ALT_MASK));
			item.addActionListener(this);
			
			if(item.isAuthenticable())
			{
				boolean permiso = getPermisos().contains(element.getAttribute("id"));
				item.setEnabled(permiso);
			}
			return item;
		}
	}
	
	public abstract Set<String> getPermisos();

	public static void setUser(String userP) {
		user = userP;
	}
	
	public static String getUser()
	{
		return user;
	}
}
